/*******************************************************************
 *
 * Copyright (C), 2021-2022, LS, All rights reserved.
 *
 * Author      : 
 * Create Time : 2020-12-15
 * Version     : v0.1
 * Description : 
 *******************************************************************/
 
/*----------------------------Head file----------------------------*/
#include "string.h"
#include "bsp_hw_config.h"
#include "ls_ble_adpter.h"
#include "ls_ble_ota_flash.h"
#include "ls_ble_sdk_config.h"
#include "ls_ble_file_ota_api.h"
#include "ls_ble_file_protocol.h"

#if (LS_BLE_FILE_SVC_ENABLE)

#define BLE_FILE_OTA_LOG_EN  1
#if BLE_FILE_OTA_LOG_EN
#include "ls_ble_log.h"
#define TAG                             "ble_file_ota"
#define BLE_FILE_OTA_LOG(level, ...)    LS_BLE_LOG_PRINT(level, TAG, __VA_ARGS__)
#else
#define BLE_FILE_OTA_LOG(...)
#endif

/*----------------------------macro file---------------------------*/
#define file_ota_flash_erase_sector(addr)    ls_ble_adpter_flash_erase_sector(addr)
#define file_ota_flash_write				 ls_ble_adpter_flash_write
#define file_ota_flash_read                  ls_ble_adpter_flash_read

/*----------------------------type define--------------------------*/

/*----------------------------var define---------------------------*/							
static ota_info_t ota_info;

/*-------------------------func declaration------------------------*/

/*-----------------------------------------------------------------*/


uint8_t ls_ble_file_set_ota_info(uint8_t *payload, uint16_t payload_len, file_trans_t* file_trans)
{
    if(payload_len < sizeof(ota_info_t)) {
        LS_BLE_LOG_RAW_INFO("payload_len err.\n");
        return OTA_INFO_TYPE_ERROR;
    }
    
    ota_info_t* info = (ota_info_t*)payload;
    
    if(OTA_FILE_TYPE_APP != info->file_type) {
        LS_BLE_LOG_RAW_INFO("Err file_type: %d.\n", info->file_type);
        return OTA_INFO_TYPE_ERROR;
    }
    
    if(info->file_len <= 0 || info->file_len > APP_IMG_MAX_SIZE) {
        LS_BLE_LOG_RAW_INFO("Err file_len: %d.\n", info->file_len);
        return OTA_INFO_SIZE_ERROR;
    }
    
    if(DEVICE_TYPE != info->dev_type) {
        LS_BLE_LOG_RAW_INFO("Err dev_type: %d.\n", info->dev_type);
        return OTA_INFO_DEV_TYPE_ERR;
    }
    
    if(PROJECT_NUM != info->project_num) {
        LS_BLE_LOG_RAW_INFO("Err project_num: %d.\n", info->project_num);
        return OTA_INFO_PROJ_NUM_ERR;
    }
    
    memset(&ota_info, 0, sizeof(ota_info));
    memcpy(&ota_info, (uint8_t*)info, sizeof(ota_info_t));
    
    LS_BLE_LOG_RAW_INFO("file_type: %d.\n", ota_info.file_type);
    LS_BLE_LOG_RAW_INFO("file_len: %d.\n", ota_info.file_len);
    LS_BLE_LOG_RAW_INFO("dev_type: %d.\n", ota_info.dev_type);
    LS_BLE_LOG_RAW_INFO("project_num: %d.\n", ota_info.project_num);
    LS_BLE_LOG_RAW_INFO("version: %d.\n", ota_info.version);
    LS_BLE_LOG_RAW_INFO("file_crc16: %d.\n", ota_info.file_crc16);
    
    file_trans->running = true;
    file_trans->offset = 0;
    file_trans->file_type = FILE_TYPE_OTA;
    ota_flash_area_erase(ota_info.file_len);
    
    return 0;
}


bool ls_ble_file_ota_rx_raw_data_handle(uint8_t *data, uint16_t data_len, file_trans_t* file_trans)
{
    if(FILE_TYPE_OTA != file_trans->file_type)
        return false;
    
    file_ota_flash_write(OTA_IMG_START_ADDR + file_trans->offset, data, data_len);
    file_trans->offset += data_len;
    LS_BLE_LOG_RAW_INFO("offset: %d\n", file_trans->offset);
    
    return true;
}


uint8_t ls_ble_file_ota_trans_done_handle(file_trans_t* file_trans)
{
    if(FILE_TYPE_OTA != file_trans->file_type)
        return 0xFF;

    uint8_t err_code = 0;
    uint8_t valid_cnt = 0;
    uint8_t try = 0;
    for(try=0;try<3;try++) {
        valid_cnt = 0;
        if(true == ota_flash_check_header(ota_info.file_len)) {
            valid_cnt++;
        }
        else {
            err_code = FILE_DONE_CONTENT_ERR;
            continue;
        }
        
        if(true == ota_flash_calculate_checksum(ota_info.file_crc16, ota_info.file_len)) {
            valid_cnt++;
        }
        else {
            err_code = FILE_DONE_CRC_ERR;
            continue;
        }
        
        if(valid_cnt >= 2) {
            err_code = 0;
            ota_flash_image_acitve();
            LS_BLE_LOG_RAW_INFO("ota_flash_image_acitve\n");
            break;
        }
    }
    if(try >= 3) {
        BLE_FILE_OTA_LOG(LOG_LVL_ERROR, "file ota crc check fail: %d, %d", err_code, file_trans->offset);
    }
    
    return err_code;
}

#endif
